package com.fly.demo.web;

import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.fly.demo.JsonResult;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Api(tags = "接口并发控制2")
@RestController
@RequestMapping(value = "/both2", produces = "application/json; charset=utf-8")
public class ConcurrentController2
{
    private int max = 5;
    
    ExecutorService executorService = Executors.newFixedThreadPool(max);
    
    Map<String, JsonResult<?>> resultMap = new ConcurrentHashMap<>();
    
    /**
     * 仅用于计数
     */
    AtomicInteger count = new AtomicInteger(0);
    
    /**
     * TODO: 待调试
     * 
     * @return
     * @throws InterruptedException
     */
    @ApiOperation("并发测试newFixedThreadPool")
    @GetMapping("/query/newFixedThreadPool")
    public JsonResult<?> newFixedThreadPool()
        throws InterruptedException
    {
        String requestId = UUID.randomUUID().toString();
        
        // 区别1: submit有返回值，而execute没有
        // 区别2: submit方便Exception处理
        executorService.execute(() -> {
            try
            {
                log.info("计数器自增：{}", count.incrementAndGet());
                
                // 模拟耗时业务操作
                log.info("业务处理开始......");
                TimeUnit.SECONDS.sleep(2);
                resultMap.put(requestId, JsonResult.success(requestId));
            }
            catch (InterruptedException e)
            {
                log.error(e.getMessage());
            }
            finally
            {
                log.info("计数器自减：{}", count.decrementAndGet());
            }
        });
        while (!resultMap.containsKey(requestId))
        {
            TimeUnit.MICROSECONDS.sleep(50);
        }
        return resultMap.get(requestId);
    }
}
